home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
398
/
398.xpi
/
chrome
/
forecastfox.jar
/
content
/
utilities
/
manager-service.js
< prev
Wrap
Text File
|
2010-02-04
|
36KB
|
1,278 lines
/*------------------------------------------------------------------------------
Copyright (c) 2008 Ensolis, LLC. All Rights Reserved.
----------------------------------------------------------------------------*/
/******************************************************************************
* Timer constants
*****************************************************************************/
const DEFAULT_DELAY = ONE_SECOND/100;
/******************************************************************************
* Front-end Preference Constants
*****************************************************************************/
const OBSERVER_PREFS = {
"units.current": true,
"general.locid": true,
"general.bar": true,
"general.position": true,
"general.last": true,
"general.delay": true,
"general.radar": true,
"radar.panel.enabled": true,
"radar.panel.display": true,
"radar.panel.label": true,
"radar.tooltip.enabled": true,
"radar.tooltip.display": true,
"radar.tooltip.title": true,
"radar.tooltip.label": true,
"hbh.panel.enabled": true,
"fiveday.panel.enabled": true,
"swa.panel.enabled": true,
"swa.panel.display": true,
"swa.panel.label": true,
"swa.tooltip.enabled": true,
"swa.tooltip.display": true,
"swa.tooltip.title": true,
"swa.tooltip.label": true,
"cc.panel.enabled": true,
"cc.panel.display": true,
"cc.panel.label": true,
"cc.tooltip.enabled": true,
"cc.tooltip.display": true,
"cc.tooltip.title": true,
"cc.tooltip.label": true,
"dayt.panel.mode": true,
"dayt.panel.switch": true,
"dayt.panel.enabled": true,
"dayt.panel.display": true,
"dayt.panel.label": true,
"dayt.tooltip.enabled": true,
"dayt.tooltip.display": true,
"dayt.tooltip.title": true,
"dayt.tooltip.label": true,
"dayf.panel.mode": true,
"dayf.panel.days": true,
"dayf.panel.enabled": true,
"dayf.panel.display": true,
"dayf.panel.label": true,
"dayf.tooltip.enabled": true,
"dayf.tooltip.display": true,
"dayf.tooltip.title": true,
"dayf.tooltip.label": true
};
/******************************************************************************
* Main interface used for interacting with the back-end. All
* service requests should go through this interface.
*
* @status FROZEN
* @version 1.0
******************************************************************************/
function ManagerService()
{
//setup additional interfaces
if (checkAlertService() && "nsIAlertListener" in Ci)
this._ifaces.push(Ci.nsIAlertListener);
this._ifaces.push(Ci.nsIObserver);
this._ifaces.push(Ci.nsISupportsWeakReference);
this._ifaces.push(Ci.nsIWebProgressListener);
//setup a new error
this._error = Cc["@ensolis.com/forecastfox/error-item;1"].
createInstance(Ci.ffIErrorItem);
}
ManagerService.prototype = {
__proto__: new ServiceBase("ManagerService"),
_obSvc: null,
_state: "stopped",
_isUpdating: null,
_isLoading: null,
_updateData: null,
_updateTimer: null,
_updateRequest: null,
_updateError: null,
_radarPersist: null,
_radarFile: null,
_errorTimer: null,
_alertTimer: null,
_serializeTimer: null,
_partner: "forecastfox",
_services: null,
_cacheSvc: null,
_ioSvc: null,
///////////////////////////
// nsIAlertListener
onAlertFinished: function ManagerService_onAlertFinished(aCookie)
{
//get the icon URL
var cookie = eval(aCookie);
var icon = cookie[1];
if (icon == "")
return;
//remove entry from cache
this.evictImage(icon);
},
onAlertClickCallback: function ManagerService_onAlertClickCallback(aCookie)
{
var cookie = eval(aCookie);
var where = getPref("links.alert");
openLink(cookie[1], where);
},
///////////////////////////
// nsIWebProgressListener
onLocationChange: function ManagerService_onLocationChange(aWebProgress, aRequest, aLocation) {},
onProgressChange: function ManagerService_onProgressChange(aWebProgress, aRequest, aCurSelfProgress, aXaxSelfProgress, aCurTotalProgress, aMaxTotalProgress ) {},
onSecurityChange: function ManagerService_onSecurityChange(aWebProgress, aRequest, aState) {},
onStatusChange: function ManagerService_onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {},
onStateChange: function ManagerService_onStateChange(aWebProgress, aRequest, aStateFlags, aStatus)
{
//only do when state is done
var stateDone = Ci.nsIWebProgressListener.STATE_STOP;
if (stateDone != (aStateFlags & stateDone))
return;
//end the radar update
this._endRadar();
},
/////////////////////////////
// nsIObserver
observe: function ManagerService_observe(aSubject, aTopic, aData)
{
switch (aTopic) {
//application shutdown
case "xpcom-shutdown":
this._state = null;
this._obSvc.removeObserver(this, "profile-before-change");
this._obSvc.removeObserver(this, "xpcom-shutdown");
this._obSvc = null;
break;
//application profile is changing
case "profile-before-change":
this.stop();
break;
//timer fired
case "timer-callback":
switch (aSubject) {
//update timer fired
case this._updateTimer:
this._startUpdate();
break;
//alert timer fired
case this._alertTimer:
this._startAlert();
break;
//error timer fired
case this._errorTimer:
//abort the request
if (this._updateRequest) {
this._updateRequest.abort();
this._updateRequest.onload = null;
this._updateRequest.onerror = null;
this._updateRequest = null;
}
//set the error
const PREFIX = "ff.manager.timeout.";
var name = this.bundle.GetStringFromName(PREFIX + "name");
var message = this.bundle.GetStringFromName(PREFIX + "message");
this._error.init(SEVERITY_ERROR, name, message);
//finish the update
this._finishUpdate(false);
break;
//serialize timer fired
case this._serializeTimer:
this._serializeCache();
break;
}
break;
//alert went away by itself
case "alertfinished":
this.onAlertFinished(aData);
break;
//user clicked alert
case "alertclickcallback":
this.onAlertClickCallback(aData);
break;
//profile notification
case "forecastfox-profiles":
//ignore except current and endBatch
if (aData != "current" && aData !="endBatch")
return;
//ignore change if it is loading or batch
if (this.profiles.isLoading || this.profiles.isBatch)
return;
this._updateData = this._getData();
this._scheduleTimer(DEFAULT_DELAY);
break;
//icon notification
case "forecastfox-icons":
//ignore except current and endBatch
if (aData != "current" && aData !="endBatch")
return;
//ignore change if it is loading or batch
if (this.icons.isLoading || this.icons.isBatch)
return;
this._updateData = this._getData();
this._scheduleTimer(DEFAULT_DELAY);
break;
//preference changed
case "nsPref:changed":
//ignore preferences the front-end does not care about
if (!OBSERVER_PREFS.hasOwnProperty(aData))
return;
//ignore if profile service loading and not an excluded pref
if (!EXCLUDED_PREFS.hasOwnProperty(aData) &&
(this.profiles.isLoading ||
this.profiles.isBatch))
return;
switch (aData) {
//preference causing us to force an update from the server
case "general.locid":
case "units.current":
this._updateData = this._getData();
this._updateData["force"] = true;
this._scheduleTimer(DEFAULT_DELAY);
break;
//preferences causing us to reload
case "general.last":
case "general.delay":
case "general.radar":
case "radar.panel.enabled":
//ignore if we are setting these prefs
if (this.isLoading)
return;
this._updateData = this._getData();
this._scheduleTimer(DEFAULT_DELAY);
break;
//all other preference causing the front-end to redisplay
default:
this._obSvc.notifyObservers(this, "forecastfox-manager", "display");
break;
}
break;
}
},
///////////////////////////
// ffIService
start: function ManagerService_start()
{
//do nothin if already running
if (this.isRunning)
return false;
//set state to starting
this._state = "starting";
//setup variables
this._isUpdating = false;
this._isLoading = false;
this._updateError = 0;
this._services = {};
this._ioSvc = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
this._cacheSvc = Cc["@mozilla.org/image/cache;1"].
getService(Ci.imgICache);
//setup timers
this._updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._errorTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._alertTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._serializeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
//ping server
this.ping.run();
//make sure we have the profile and icon service started
var current = this.profiles.current;
current = this.icons.current;
//setup update data
this._updateData = this._getData();
//add observers
this._obSvc = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
this._obSvc.addObserver(this, "forecastfox-profiles", true);
this._obSvc.addObserver(this, "forecastfox-icons", true);
this._obSvc.addObserver(this, "profile-before-change", true);
this._obSvc.addObserver(this, "xpcom-shutdown", true);
//add prefernce observer
var pb2 = this.branch.QueryInterface(Ci.nsIPrefBranchInternal);
pb2.addObserver("", this, true);
//return success
this._state = "started";
return true;
},
stop: function ManagerService_stop()
{
//do nothin if not running
if (!this.isRunning)
return;
//set state to stopping
this._state = "stopping";
//remove preference observers
var pb2 = this.branch.QueryInterface(Ci.nsIPrefBranchInternal);
pb2.removeObserver("", this);
//remove notification observers
if (this._obSvc) {
this._obSvc.removeObserver(this, "forecastfox-profiles");
this._obSvc.removeObserver(this, "forecastfox-icons");
}
//stops timers and aborts requests
this._endUpdate();
//stop components
for (var name in this._services) {
/* do not stop the disk service because other service
depend on it in the flushData method */
if (name == "DiskService")
continue;
//stop the component
var contractID = gComponents[name].contractID;
var interfaceID = gComponents[name].interfaceID;
var service = Cc[contractID].getService(interfaceID);
service.stop();
delete this._services[name];
}
//stop the disk service
name = "DiskService";
if (this._services.hasOwnProperty(name)) {
contractID = gComponents[name].contractID;
interfaceID = gComponents[name].interfaceID;
service = Cc[contractID].getService(interfaceID);
service.stop();
delete this._services[name];
}
//destroy variables
this._isUpdating = null;
this._isLoading = null;
this._updateData = null;
this._updateTimer = null;
this._updateRequest = null;
this._updateError = null;
this._radarPersist = null;
this._radarFile = null;
this._errorTimer = null;
this._alertTimer = null;
this._serializeTimer = null;
this._partner = null;
this._services = null;
this._ioSvc = null;
this._cacheSvc = null;
//set state to stopped
this._state = "stopped";
},
///////////////////////////
// ffIManagerService
/**
* Service is currently running.
*/
get isRunning() {
if (this._state == "starting" ||
this._state == "started")
return true;
return false;
},
/**
* Service is updating data.
*/
get isUpdating() { return this._isUpdating; },
/**
* Service is being loaded into preferences.
*/
get isLoading() { return this._isLoading; },
/**
* Run an update. Called from the a dom window.
*
* @param Force the update from the server.
*/
run: function ManagerService_run(aForce)
{
//start the service if it has not been started
if (!this.isRunning)
this.start();
//set the forced attribute
this._updateData["force"] = aForce;
//schedule an update
this._scheduleTimer(DEFAULT_DELAY);
},
/**
* Open a link in the main application window
*
* @param The url to open.
* @param Where to open the link (current, window, tab, tabshifted)
*/
openLink: function ManagerService_openLink(aURL, aWhere)
{
openLink(aURL, aWhere);
},
/**
* Gets a preference.
*
* @param Name of the preference to retrieve.
* @return Requested preference value.
*/
getPref: function ManagerService_getPref(aName)
{
return getPref(aName);
},
/**
* Sets a preference.
*
* @param Name of the preference to retrieve.
* @param Value to set the preference to.
*/
setPref: function ManagerService_setPref(aName, aValue)
{
setPref(aName, aValue);
},
/**
* Evict an image from the cache.
*
* @param The image URL.
*/
evictImage: function ManagerService_evictImage(aURL)
{
//convert the URL to a URI
var URI = this._ioSvc.newURI(aURL, null, null);
//evict the image
try {
this._cacheSvc.removeEntry(URI);
} catch(e) {}
},
/**
* Partner id used in link parameters.
*/
get partner() { return this._partner; },
/**
* ffIDiskService component.
*/
get disk() { return this._getService("DiskService"); },
/**
* ffIPingService component.
*/
get ping() { return this._getService("PingService"); },
/**
* ffIConverterService component.
*/
get converters() { return this._getService("ConverterService"); },
/**
* ffIParserService component.
*/
get parser() { return this._getService("ParserService"); },
/**
* ffIProfileService component.
*/
get profiles() { return this._getService("ProfileService"); },
/**
* ffIMigratorService component.
*/
get migrator() { return this._getService("MigratorService"); },
/**
* ffIPackService component.
*/
get icons() { return this._getService("PackService"); },
////////////////////////////////
// Internal Functions
/**
* Start a data update.
*/
_startUpdate: function ManagerService__startUpdate()
{
//end previous update
this._endUpdate();
//do nothing if location not set
if (!this._checkID())
return;
//mark we are updating
this._isUpdating = true;
//notify observers of update
this._obSvc.notifyObservers(this, "forecastfox-manager", "startUpdate");
//check if we need to come from server
this._updateData["server"] = this._checkServer();
//clear last error
this._error.init(SEVERITY_INFO, "", "");
//parse from cache
if (!this._updateData["server"]) {
var success = this.parser.parseCache(this._getCache());
this._finishUpdate(success);
//request from server
} else {
//create the xml request
var comp = this;
this._updateRequest = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
createInstance(Ci.nsIXMLHttpRequest);
this._updateRequest.overrideMimeType("text/xml; charset=iso-8859-1");
this._updateRequest.onerror = function() { comp._onRequestLoad(); };
this._updateRequest.onload = function() { comp._onRequestLoad(); };
this._updateRequest.open("GET", this._getServer(), true);
//set the channel bypass cache flag
this._updateRequest.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
//set the channel priority
if ("nsISupportsPriority" in Ci) {
if (this._updateRequest.channel instanceof Ci.nsISupportsPriority)
this._updateRequest.channel.priority = Ci.nsISupportsPriority.
PRIORITY_LOWEST;
}
//send the request and start the error timer (40 seconds)
this._errorTimer.init(this, ONE_MINUTE, Ci.nsITimer.TYPE_ONE_SHOT);
this._updateRequest.send(null);
}
},
/**
* End a data update.
*/
_endUpdate: function ManagerService__endUpdate()
{
//do nothing if not updating
if (!this.isUpdating)
return;
//stop the alert timer
if (this._alertTimer)
this._alertTimer.cancel();
//stop the error timer
if (this._errorTimer)
this._errorTimer.cancel();
//stop the update timer
if (this._updateTimer)
this._updateTimer.cancel();
//stop the serialize timer
if (this._serializeTimer)
this._serializeTimer.cancel();
//mark that we are done updating
this._isUpdating = false;
//cancel pending persist
if (this._radarPersist) {
this._radarPersist.cancelSave();
this._radarPersist.progressListener = null;
this._radarPersist = null;
this._radarFile = null;
}
//cancel pending request
if (this._updateRequest) {
this._updateRequest.abort();
this._updateRequest.onload = null;
this._updateRequest.onerror = null;
this._updateRequest = null;
}
//notify observers
if (this._obSvc)
this._obSvc.notifyObservers(this, "forecastfox-manager", "endUpdate");
},
/**
* Callback from the xml request.
*/
_onRequestLoad: function ManagerService__onRequestLoad()
{
//stop the error timer
this._errorTimer.cancel();
//get error values
const PREFIX = "ff.manager.";
var name = "";
var message = "";
//check if we actual received anything
if (this._updateRequest.responseText == "") {
name = this.bundle.GetStringFromName(PREFIX + "connect.name");
message = this.bundle.GetStringFromName(PREFIX + "connect.message");
this._error.init(SEVERITY_ERROR, name, message);
this._finishUpdate(false);
return;
}
//get the request status
var status = -1;
try {
status = this._updateRequest.status;
} catch (e) {}
//check the status
switch (status) {
//no error
case 200:
break;
//authentication error
case 407:
name = this.bundle.GetStringFromName(PREFIX + "auth.name");
message = this.bundle.GetStringFromName(PREFIX + "auth.message");
this._error.init(SEVERITY_ERROR, name, message);
this._finishUpdate(false);
return;
//connection error
case -1:
name = this.bundle.GetStringFromName(PREFIX + "connect.name");
message = this.bundle.GetStringFromName(PREFIX + "connect.message");
this._error.init(SEVERITY_ERROR, name, message);
this._finishUpdate(false);
return;
//network error
default:
name = this.bundle.GetStringFromName(PREFIX + "net.name");
message = this.bundle.formatStringFromName(PREFIX + "net.message",
[status], 1);
this._error.init(SEVERITY_ERROR, name, message);
this._finishUpdate(false);
return;
}
//parse the document
var dom = this._updateRequest.responseXML;
var success = this.parser.parseDOM(dom);
//save the expires information - default to 15 minutes
var expires = (new Date()).getTime() + (15*ONE_MINUTE);
this._updateData["expires"] = expires;
//clear the request
this._updateRequest.onload = null;
this._updateRequest.onerror = null;
this._updateRequest = null;
//finish the update if not successful
if (!success)
this._finishUpdate(success);
//otherwise fire the serialize timer
this._serializeTimer.init(this, DEFAULT_DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
},
/**
* Do function required once an update has completed.
*
* @param Success code from parsing or serializing cache.
*/
_finishUpdate: function ManagerService__finishUpdate(aSuccess)
{
//update was not successful
if (!aSuccess) {
//force from server next time
this._updateData["force"] = true;
//set the error if it has not been set
var err = this.lastError;
if (err.severity == SEVERITY_INFO) {
err = this.parser.lastError;
this._error.init(err.severity, err.name, err.message);
}
//update was successful
} else {
//remove the force for next time
this._updateData["force"] = false;
//update was from the server
if (this._updateData["server"]) {
//save the update data
this._saveData();
//set the alert slider on a 1 second delay
if (checkAlertService())
this._alertTimer.init(this, ONE_SECOND, Ci.nsITimer.TYPE_ONE_SHOT);
}
//check if we need to get the radar
if (this._checkRadar()) {
this._startRadar();
return;
}
}
//mark the update is complete
this._isUpdating = false;
//notify observers
this._obSvc.notifyObservers(this, "forecastfox-manager", "endUpdate");
//schedule the next update
this._scheduleTimer();
},
/**
* Serialize the cache data to disk.
*/
_serializeCache: function ManagerService__serializeCache()
{
//serialize data to disk
var success = this.parser.serializeCache(this._getCache());
//finish the update process
this._finishUpdate(success);
},
/**
* Check if the location id is set.
*
* @return True if location is set otherwise false.
*/
_checkID: function ManagerService__checkID()
{
//get the location id
var locid = this._updateData["general.locid"];
//if the locid hasn't been set yet, prompt for it
var url = "chrome://forecastfox/content/options/options.xul";
if (locid == "00000" || locid == "") {
//focus the options window if already open
var mediator = Cc['@mozilla.org/appshell/window-mediator;1'].
getService(Ci.nsIWindowMediator);
var options = mediator.getMostRecentWindow("forecastfox:options");
if (options)
options.focus();
//open a new options window
else
getTopWindow().openDialog(url, "options", "chrome,modal");
//return failed
return false;
}
//return success
return true;
},
/**
* Check if the data needs to come from the server.
*
* @return True or False.
*/
_checkServer: function ManagerService__checkServer()
{
//check if forced
if (this._updateData["force"])
return true;
//check the cache
if (!this._checkCache())
return true;
//get the current date/time
var current = (new Date()).getTime();
//get the delay and make sure it is greater than 0;
var delay = this._updateData["general.delay"];
if (delay < 0)
delay = 30;
//determine the next update time
var last = Number(this._updateData["general.last"]);
var next = last + (delay*ONE_MINUTE);
//check if the last update occurred in the future
if (last > current)
return true;
//check if it has been the allowed time
if (((next - current) <= DEFAULT_DELAY))
return true;
//from cache
return false;
},
/**
* Check if the data can come from the cache.
*
* @return True if the cache file exists.
*/
_checkCache: function ManagerService__checkCache()
{
var file = this._getCache();
if (!file.exists())
return false;
return true;
},
/**
* Check if we need to get the radar image.
*
* @return True if the radar image is required.
*/
_checkRadar: function ManagerService__checkRadar()
{
//check if the panel is enabled
if (!this._updateData["radar.panel.enabled"])
return false;
//check if there is a url for the radar
var URL = this.parser.getValue("radar", 0, "imagelarge", null);
if (!URL || URL == "N/A")
URL = this.parser.getValue("radar", 0, "image", null);
if (!URL || URL == "N/A")
return false;
//check if the file exists
var name = "radar-" + this._updateData["profile.current"] + ".gif";
var file = this.disk.get(name, TYPE_CACHE);
if (!file.exists())
return true;
//check the radar last
if (Number(this._updateData["general.radar"]) >
Number(this._updateData["general.last"]))
return false;
//we need radar
return true;
},
/**
* Get the update data from preferences.
*/
_getData: function ManagerService__getData()
{
//create the data object
var data = {};
//set its properties
data["profile.current"] = getPref("profile.current");
data["general.last"] = getPref("general.last");
data["general.locid"] = getPref("general.locid");
data["general.delay"] = getPref("general.delay");
data["general.radar"] = getPref("general.radar");
data["units.current"] = getPref("units.current");
data["radar.panel.enabled"] = getPref("radar.panel.enabled");
data["server"] = true;
data["force"] = false;
data["expires"] = null;
//return the data object
return data;
},
/**
* Build the update server url.
*
* @return The url used in the xml request.
*/
_getServer: function ManagerService__getServer()
{
var URL = "http://forecastfox.accuweather.com/adcbin/forecastfox/weather_data.asp?";
URL += "location=" + this._updateData["general.locid"];
//set units
URL += "&metric=" + this._updateData["units.current"];
//add partner
URL += "&partner=" + this.partner;
//return string
return URL;
},
/**
* Get the feed cache file.
*
* @return A object implementing the nsIFile interface.
*/
_getCache: function ManagerService__getCache()
{
var name = "feed-" + this._updateData["profile.current"] + ".js";
return this.disk.get(name, TYPE_CACHE);
},
/**
* Save the update data to preferences.
*/
_saveData: function ManagerService__saveData()
{
//set a new delay if we have the expires property
var current = (new Date()).getTime();
if (this._updateData["expires"] != null) {
//get the next time
var next = this._updateData["expires"];
//get the delay
var delay = (next-current)/(ONE_MINUTE);
//add a random number of minutes to it
var random = 1 + Math.random()*2;
delay = Math.floor(delay + random);
//make sure the delay is rational
if (delay > -5 && delay <= 0)
delay = 5;
if (delay < 0 || delay > 30)
delay = 30;
//save the delay and clear the expires
this._updateData["general.delay"] = delay;
this._updateData["expires"] = null;
}
//set the last property
this._updateData["general.last"] = String(current);
//set the preferences
this._isLoading = true;
setPref("general.last", this._updateData["general.last"]);
setPref("general.delay", this._updateData["general.delay"]);
this._isLoading = false;
},
/**
* Start the radar update.
*/
_startRadar: function ManagerService__startRadar()
{
//get the radar url
var URL = this.parser.getValue("radar", 0, "imagelarge", null);
if (!URL || URL == "N/A")
URL = this.parser.getValue("radar", 0, "image", null);
//convert the url to a uri
var ioSvc = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var URI = ioSvc.newURI(URL, null, null);
//get a temp file to persist to
var name = "radar-" + this._updateData["profile.current"] + ".gif";
this._radarFile = this.disk.get(name, TYPE_TEMP);
//setup the persist object
var flags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE |
Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
this._radarPersist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].
createInstance(Ci.nsIWebBrowserPersist);
this._radarPersist.persistFlags |= flags;
this._radarPersist.progressListener = this;
this._radarPersist.saveURI(URI, null, null, null, null, this._radarFile);
},
/**
* End the radar update
*/
_endRadar: function ManagerService__endRadar()
{
//copy the file to correct location
var name = "radar-" + this._updateData["profile.current"] + ".gif";
var file = this.disk.get(name, TYPE_CACHE);
this.disk.copy(this._radarFile, file);
//evict the image from the cache
var URL = this.disk.getFileURL(this._radarFile);
this.evictImage(URL);
//remove the old file
try {
removeFile(this._radarFile);
} catch(e) {}
//save the radar time
this._isLoading = true;
var current = String((new Date()).getTime());
this._updateData["general.radar"] = current;
setPref("general.radar", current);
this._isLoading = false;
//clear the persist
this._radarFile = null;
this._radarPersist.progressListener = null;
this._radarPersist = null;
//mark update finished
this._isUpdating = false;
//notify front-end
this._obSvc.notifyObservers(this, "forecastfox-manager", "endUpdate");
//schedule the next update
this._scheduleTimer();
},
/**
* Start the alert slider.
*/
_startAlert: function ManagerService__startAlert()
{
//always increment count for cc when called
var count = getPref("cc.slider.count");
setPref("cc.slider.count", count + 1);
//determine if a swa is active
var active = false;
if (this.parser.getValue("swa", 0, "active", null) == "true")
active = true;
//if active determine if we should show it
var enabled = false;
var freq = 0;
if (active) {
//always increment count for swa if active
count = getPref("swa.slider.count");
setPref("swa.slider.count", count + 1);
//show swa
enabled = getPref("swa.slider.enabled");
freq = getPref("swa.slider.freq");
if (enabled && count == 1) {
this._endAlert("swa");
return;
}
//reset the count to 1
if (count >= freq)
setPref("swa.slider.count", 1);
} else
setPref("swa.slider.count", 1);
//show current
enabled = getPref("cc.slider.enabled");
freq = getPref("cc.slider.freq");
if (enabled && count >= freq) {
setPref("cc.slider.count", 1);
this._endAlert("cc");
}
},
/**
* Actually show the required alert slider.
*
* @param The prefix of the item to show.
*/
_endAlert: function ManagerService__endAlert(aPrefix)
{
//get the parser target
var target = (aPrefix == "cc") ? "current" : "swa";
//get the current icon pack
var pack = this.icons.current;
var parser = this.parser;
//get the display options
var display = getPref(aPrefix + ".slider.display");
var title = getPref(aPrefix + ".slider.title");
var label = getPref(aPrefix + ".slider.label");
var icon = parser.getValue(target, 0, "icon", null);
var url = parser.getValue(target, 0, "url", null);
switch (display) {
//only show icons
case 0:
icon = pack.getItem(icon + "-large").URL;
title = "";
label = "";
break;
//only show text
case 1:
icon = "";
title = parser.getLabel(title, target, 0);
label = parser.getLabel(label, target, 0);
break;
//show both
case 2:
icon = pack.getItem(icon + "-large").URL;
title = parser.getLabel(title, target, 0);
label = parser.getLabel(label, target, 0);
break;
}
//do alert
var alSvc = Cc["@mozilla.org/alerts-service;1"].
getService(Ci.nsIAlertsService);
var cookie = [icon, url].toSource();
alSvc.showAlertNotification(icon, title, label, true, cookie, this);
},
/**
* Schedule the update timer.
*
* @param The timer delay, override default times.
*/
_scheduleTimer: function ManagerService__scheduleTimer(aOverride)
{
//cancel previous timer
this._updateTimer.cancel();
//use the override delay
if (aOverride) {
this._updateTimer.init(this, aOverride, Ci.nsITimer.TYPE_ONE_SHOT);
return;
}
//get our error status
var delay = 0;
var err = (this.lastError.severity == SEVERITY_INFO) ? false : true;
//if not an error then schedule normal time
if (!err) {
delay = this._updateData["general.delay"]*ONE_MINUTE;
this._updateError = 0;
//error occurred from cache set delay to 10
} else if (!this._updateData["server"]) {
delay = DEFAULT_DELAY;
this._updateError = 0;
//error occurred form server
} else {
//ten seconds for the first error
if (this._updateError == 0) {
delay = 10*ONE_SECOND;
this._updateError++;
//progressively more minutes with each additional error
} else {
delay = this._updateError*ONE_MINUTE;
this._updateError++;
}
}
//setup the timer
this._updateTimer.init(this, delay, Ci.nsITimer.TYPE_ONE_SHOT);
},
/**
* Retrieve a service from our services object.
*
* @param Name of the service.
* @return The requested service and interface.
*/
_getService: function ManagerService__getService(aName)
{
//get the service
var contractID = gComponents[aName].contractID;
var interfaceID = gComponents[aName].interfaceID;
var service = Cc[contractID].getService(interfaceID);
var prompter = getPrompter(getTopWindow());
try {
//check if service has been started before
if (!this._services.hasOwnProperty(aName))
this._services[aName] = service.start();
//service did not start successfully
if (!this._services[aName]) {
var err = service.lastError;
this.disk.log("The following service: " + aName + " returned an error: " + err.toString(), null, null);
prompter.alert(err.name, err.message);
delete this._services[aName];
return null;
}
//return the service
return service;
//service threw an error
} catch (e) {
this.disk.log("Error starting the following service: " + aName, e, null);
prompter.alert(e.name, e.message);
delete this._services[aName];
}
//service not started successfully
return null;
}
};